package pt.elvis.revanweb.client.uiBinders;

import java.util.ArrayList;
import java.util.List;

import pt.elvis.revanweb.client.RevanWeb;
import pt.elvis.revanweb.client.DatabaseObjects.Bookmarks_Objects;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SubmitButton;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TabLayoutPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.visualization.client.AbstractDataTable;
import com.google.gwt.visualization.client.AbstractDataTable.ColumnType;
import com.google.gwt.visualization.client.DataTable;
import com.google.gwt.visualization.client.VisualizationUtils;
import com.google.gwt.visualization.client.visualizations.Table;
import com.google.gwt.visualization.client.visualizations.Table.Options.Policy;
import com.google.gwt.visualization.client.visualizations.corechart.BarChart;
import com.google.gwt.visualization.client.visualizations.corechart.Options;

/**
 * @author <b>Elvis Pestana</b>
 * @author It's where new bookmarks can be added or edited in the database. Also
 *         allows to see statistics related to how often is a specific bookmarks
 *         is used.
 * 
 * @return Returns a TabLayoutPanel.
 * 
 * @see TabLayoutPanel
 **/

public class AdminPanel extends Composite {

	private EditableFlexTable editTable;
	private final int rowsPerPage = 15;
	private final String SESSION_ID;
	
	//Chart variables
	private BarChart barChart;
	private Table tableChart;
	
	private Timer timer = new Timer() {

		@Override
		public void run() {
			lblWarning.setVisible(false);
		}
	};
	
	private static AdminPanelUiBinder uiBinder = GWT
			.create(AdminPanelUiBinder.class);

	interface AdminPanelUiBinder extends UiBinder<Widget, AdminPanel> {
	}
	
	//Fields from uiBinder
	@UiField
	TabLayoutPanel tabPanel;

	// Containers
	@UiField
	VerticalPanel tabNewWrapper;
	@UiField
	HTMLPanel bookmarkNamePanel;
	@UiField
	HTMLPanel bookmarkURLPanel;
	@UiField
	HTMLPanel bookmarkDescriptionPanel;
	@UiField
	HTMLPanel bookmarkcbActivePanel;
	@UiField
	HTMLPanel bookmarkTagsPanel;
	@UiField
	HTMLPanel barChartWrapper;
	@UiField
	HTMLPanel tablechartWrapper;	
	@UiField
	SimplePanel editFlexTableWrapper;

	// Controls
	@UiField
	TextBox txtBookmarkName;

	@UiField
	TextBox txtBookmarkURL;

	@UiField
	TextArea txtBookmarkDescription;

	@UiField
	CheckBox cbActive;

	@UiField
	SuggestBox sbBookmarkTags;

	@UiField
	FormPanel formPanel;

	@UiField
	FileUpload uploadFile;

	@UiField
	Label lblWarning;

	@UiField
	Hidden sessionID;

	@UiField
	SubmitButton btnSubmit;

	public AdminPanel(String SESSION_ID) {
		this.SESSION_ID = SESSION_ID;
		initWidget(uiBinder.createAndBindUi(this));
		// Due to a Firefox layout issue, bottom: 0; is removed from style
		// element
		// tabNewWrapper.getElement().setAttribute("style",
		// "position: absolute; left: 0px; right: 0px; top: 0px;");
		tabNewWrapper.getElement().removeAttribute("style");
		tabPanel.selectTab(0);
		editFlexTableWrapper.add(editTable);
		sbBookmarkTags.getTextBox().addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				bookmarkNamePanel.removeStyleName("focused");
				bookmarkURLPanel.removeStyleName("focused");
				bookmarkDescriptionPanel.removeStyleName("focused");
				bookmarkcbActivePanel.removeStyleName("focused");
				bookmarkTagsPanel.addStyleName("focused");
			}
		});
		buildCharts();
	}
	
	public void loadEditTableInstance() {
		editTable = new EditableFlexTable(rowsPerPage, SESSION_ID);
		editFlexTableWrapper.add(editTable);
	}	
	

	@UiHandler("txtBookmarkName")
	void handleClick_txtBookmarkName(ClickEvent e) {
		bookmarkNamePanel.addStyleName("focused");
		bookmarkURLPanel.removeStyleName("focused");
		bookmarkDescriptionPanel.removeStyleName("focused");
		bookmarkcbActivePanel.removeStyleName("focused");
		bookmarkTagsPanel.removeStyleName("focused");
	}

	@UiHandler("txtBookmarkURL")
	void handleClick_txtBookmarkURL(ClickEvent e) {
		bookmarkNamePanel.removeStyleName("focused");
		bookmarkURLPanel.addStyleName("focused");
		bookmarkDescriptionPanel.removeStyleName("focused");
		bookmarkcbActivePanel.removeStyleName("focused");
		bookmarkTagsPanel.removeStyleName("focused");
	}

	@UiHandler("txtBookmarkDescription")
	void handleClick_txtBookmarkDescription(ClickEvent e) {
		bookmarkNamePanel.removeStyleName("focused");
		bookmarkURLPanel.removeStyleName("focused");
		bookmarkDescriptionPanel.addStyleName("focused");
		bookmarkcbActivePanel.removeStyleName("focused");
		bookmarkTagsPanel.removeStyleName("focused");
	}

	@UiHandler("formPanel")
	void handleOnSubmit_formPanel(SubmitEvent e) {
		sessionID.setValue(this.SESSION_ID);
	}

	@UiHandler("formPanel")
	void handleSubmitComplete(SubmitCompleteEvent e) {
		//Parse the JSON received.
		JSONValue value = JSONParser.parseStrict(e.getResults());		
		JSONObject obj = value.isObject();		
		int id = Integer.parseInt(obj.get("newID").isString().stringValue());		
		String filename;
		try {
			filename = id + uploadFile.getFilename().substring(uploadFile.getFilename().lastIndexOf('.'));
		} catch (Exception e1) {
			filename = "link.png";
		}
		if (obj.get("Success").isString().stringValue().equals("true")) {
			// Update BookmarksList before cleaning the textboxes
			RevanWeb.bookmarksList.add(new Bookmarks_Objects(id, txtBookmarkName.getText(), txtBookmarkURL.getText(), txtBookmarkDescription.getText(), "logos/" + filename, cbActive.getValue(), 0));
			txtBookmarkName.setText("");
			txtBookmarkURL.setText("");
			txtBookmarkDescription.setText("");
			cbActive.setValue(false);
			sessionID.setValue("");
			lblWarning.setText("Data saved!");
			lblWarning.setVisible(true);
			timer.schedule(10000);
		} else {
			lblWarning.setText("Incorrect session id. Please log out and try again.");
			lblWarning.setVisible(true);
			timer.schedule(10000);
			Window.alert("INSERTING NEW BOOKMARK:\n" + e.getResults());
			sessionID.setValue("");
		}
	}
	
	
	/*
	 * This handles the changing of tabs event
	 */
	@UiHandler("tabPanel")
	void handleSelect_tabPanel(SelectionEvent<Integer> e) {
		int selectedItem = e.getSelectedItem();
		switch (selectedItem) {
		case 0: //New
			
			break;
		case 1: //Edit
			{	
				while (!RevanWeb.isLoaded) { } //This holds the loading process untill all bookmarks are loaded into memory. Not exactly pretty, but get's the job done.
				int currentRow = editTable.getCurrentRow();
				if (!( currentRow < rowsPerPage))
					editTable.setCurrentRow(currentRow - rowsPerPage);
				editTable.buildEditableFlexTable();
			}
			break;
		case 2: //Statistics
			buildCharts();
			break;
		default:
			Window.alert("SOMETHING IS WRONG IN TAB PANEL SELECTION HANDLER");
			break;
		}
	}	

	public void setSelectedTab(int selectIndex) {
		tabPanel.selectTab(0);
	}
	
	private void buildCharts() {
		//Load BarChart section 
		// Create a callback to be called when the visualization API
		// has been loaded.
		Runnable onLoadCallback = new Runnable() {
			public void run() {
				barChart = new BarChart(createTable(true), barCreateOptions());
				barChartWrapper.clear();
				barChartWrapper.add(barChart);
			}
		};
		// Load the visualization api, passing the onLoadCallback to be
		// called
		// when loading is done.
		VisualizationUtils.loadVisualizationApi(onLoadCallback,
				BarChart.PACKAGE);
		
		//Load Table Section
		// Create a callback to be called when the visualization API
		// has been loaded.
		Runnable onLoadCallback2 = new Runnable() {
			public void run() {
				tableChart = new Table(createTable(false), tableCreateOptions());
				
				tablechartWrapper.clear();
				tablechartWrapper.add(tableChart);
			}			
		};
		// Load the visualization api, passing the onLoadCallback to be
		// called
		// when loading is done.
		VisualizationUtils.loadVisualizationApi(onLoadCallback2,
				Table.PACKAGE);
	}
	
	/*
	 * Sets the options for the Table in statistics tab
	 */
	private com.google.gwt.visualization.client.visualizations.Table.Options tableCreateOptions() {
		com.google.gwt.visualization.client.visualizations.Table.Options options = com.google.gwt.visualization.client.visualizations.Table.Options.create();		
		
		options.setWidth("100%");
		options.setPage(Policy.ENABLE);
		options.setPageSize(10);
		options.setShowRowNumber(true);
		return options;
	}

	/*
	 * Sets options for the Barchart in statistics tab
	 */
	private Options barCreateOptions() {
		Options options = Options.create();
		options.setWidth(600);
		options.setHeight(400);
		options.setTitle("Most used Bookmarks");
		options.setBackgroundColor("transparent");
		return options;
	}


	private AbstractDataTable createTable(boolean isBar) {		
		List<Bookmarks_Objects> bookmarksList = sortedBookmarks(RevanWeb.bookmarksList);
		DataTable data = DataTable.create();
		if (isBar) {
			for(int i = bookmarksList.size(); i > 10; i--)
				bookmarksList.remove(i - 1);					
			data.addColumn(ColumnType.STRING, "Bookmark");
			data.addColumn(ColumnType.NUMBER, "Times Clicked");
			data.addRows(bookmarksList.size());
			for (int i = 0; i < bookmarksList.size(); i++) {
				data.setValue(i, 0, bookmarksList.get(i).getBookmarkName());
				data.setValue(i, 1, bookmarksList.get(i).getBookmarkCount());
			}
		} else {
			data.addColumn(ColumnType.STRING, "Bookmark");
			data.addColumn(ColumnType.STRING, "Bookmark URL");
			data.addColumn(ColumnType.STRING, "Bookmark Description");
			data.addColumn(ColumnType.NUMBER, "Times Clicked");
			data.addRows(bookmarksList.size());
			for (int i = 0; i < bookmarksList.size(); i++) {
				data.setValue(i, 0, bookmarksList.get(i).getBookmarkName());
				data.setValue(i, 1, bookmarksList.get(i).getBookmarkURL());
				data.setValue(i, 2, bookmarksList.get(i).getBookmarkDescription());
				data.setValue(i, 3, bookmarksList.get(i).getBookmarkCount());
			}
		}
		return data;
	}

	private List<Bookmarks_Objects> sortedBookmarks(List<Bookmarks_Objects> bookmarksList) {
		List<Bookmarks_Objects> tempBookmarksList = new ArrayList<Bookmarks_Objects>();
		
		for (Bookmarks_Objects tmp : bookmarksList) {
			tempBookmarksList.add(tmp);
		}
		
		for (int i = tempBookmarksList.size(); i >= 1; i--) {
			for (int j = 1; j < i; j++) {
				if (tempBookmarksList.get(j - 1).getBookmarkCount() < tempBookmarksList.get(j).getBookmarkCount()) {
					Bookmarks_Objects aux = tempBookmarksList.get(j);
					tempBookmarksList.set(j, tempBookmarksList.get(j - 1));
					tempBookmarksList.set(j - 1, aux);
				}
			}
		}
		return tempBookmarksList;
	}
}